#pragma once

#include <iostream>
#include <pthread.h>
#include <vector>
#include <queue>
#include "Log.hpp"
#include "Thread.hpp"

const static int Defaultquantity = 5;

using namespace std;

template <typename T>
class ThreadPool
{

private:
    void LockQueue()
    {
        pthread_mutex_lock(&_mutex);
    }

    void UnLockQueue()
    {
        pthread_mutex_unlock(&_mutex);
    }

    void SleepThread()
    {
        pthread_cond_wait(&_cond,&_mutex);
    }

    void WakeUpThread()
    {
        pthread_cond_signal(&_cond);
    }
    
    void AllWakeUpThread()
    {
        pthread_cond_broadcast(&_cond);
    }

public:
    ThreadPool(int threadnum = Defaultquantity)
        : _threadnum(threadnum), _waitnum(0), _isrunning(false)
    {
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_cond,nullptr);
        Log(INFO, "%s", "ThreadPool create");
    }
    
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

    void HandlerTask(string threadname)
    {
        Log(INFO,"%s is running  ",threadname.c_str());
        while(1)
        {
            LockQueue();//保护队列的安全
            //当队列中没有数据且还在运行就等
            while(_task_queue.empty() && _isrunning==true)
            {
                ++_waitnum;
                SleepThread();
                --_waitnum;
            }//这里注意要写成循环

            //当队列中没有数据且不在运行就退出
            if(_task_queue.empty() && _isrunning==false)
            {
                UnLockQueue();
                return;
            }

            //如果队列不运行了，需要把任务队列中的任务处理完毕
            T t = _task_queue.front();
            _task_queue.pop();
            UnLockQueue();  
            Log(DEBUG,"%s get a task",threadname.c_str());
            t();
            Log(DEBUG,"%s handler a task done,rusult is:%s",threadname.c_str(),t.ResultToString().c_str());

        }

    }

    void Start()
    {
        for(auto& thread : _threads)
        {
            thread.Strat();
        }
    }

    void InitThreadPool()
    {
        for (int i = 0; i < _threadnum; i++)
        {
            string name = "thread-" + to_string(i+1);
            _threads.emplace_back(bind(&ThreadPool<Task>::HandlerTask,this,placeholders::_1),name);//绑定，为了把Handler函数写成非静态函数
            Log(INFO,"create thread %s done",name.c_str());
        }
        _isrunning = true;
    }

    void Stop()
    {
        LockQueue();
        _isrunning = false;
        AllWakeUpThread();    //需要把所有线程全部唤醒，线程才能全部退出
        UnLockQueue();
    }

    void Wait()
    {

        for(auto& thread : _threads)
        {
  
            thread.join();
            Log(INFO, "%s is quit...", thread.name().c_str());
        }
    }

    bool EnQueue(const T& t)
    {
        bool ret = false;
        LockGuard();
        if(_isrunning)
        {
            _task_queue.push(t);
            if(_waitnum>0)
            {
                WakeUpThread();
            }
            Log(DEBUG,"enqueue task success");
            ret = true;
        }

        UnLockQueue();
        return ret;
    }

private:
    int _threadnum;          // 创建线程个数
    vector<Thread> _threads; // 存放线程
    queue<T> _task_queue;      // 任务队列
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;

    int _waitnum;    // 等待的线程个数
    bool _isrunning; // 进程池是否运行
};
